package sf.dsl.example;

import sf.database.dialect.DBDialect;
import sf.database.jdbc.sql.SQLContext;
import sf.database.jdbc.sql.SQLParameter;
import sf.database.meta.ColumnMapping;
import sf.spring.util.CollectionUtils;
import sf.tools.ArrayUtils;
import sf.tools.StringUtils;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

public class PartCondition implements ICondition {
    private SimpleField[] fields;

    protected DBOperator operator;
    /**
     * 值,可为Collection子类或任意类型
     */
    protected Object value;

    /**
     * 值类型
     */
    protected ValueType valueType;

    /**
     * like中的escape
     */
    private String escape;

    public PartCondition() {

    }

    protected PartCondition(Object value) {
        this.value = value;
        this.valueType = ValueType.singleValue;
    }

    protected PartCondition(SimpleField simpleField, DBOperator operator) {
        this.fields = new SimpleField[]{simpleField};
        this.operator = operator;
        this.valueType = ValueType.noValue;
    }

    protected PartCondition(SimpleField simpleField, DBOperator operator, Object value) {
        this(simpleField, operator, value, ValueType.singleValue);
    }

    protected PartCondition(SimpleField simpleField, DBOperator operator, Collection<?> value) {
        this(simpleField, operator, value, ValueType.listValue);
    }

    protected PartCondition(SimpleField simpleField, DBOperator operator, Object[] value) {
        this(simpleField, operator, value, ValueType.arrayValue);
    }

    protected PartCondition(SimpleField simpleField, DBOperator operator, Object value, ValueType valueType) {
        this.fields = new SimpleField[]{simpleField};
        this.value = value;
        this.valueType = valueType;
        this.operator = operator;
    }

    @Override
    public SimpleTable getTable() {
        if (ArrayUtils.isNotEmpty(getFields())) {
            for (int i = 0; i < fields.length; i++) {
                if (fields[i].getTable() != null) {
                    return fields[i].getTable();
                }
            }
        }
        return null;
    }

    @Override
    public void toSql(StringBuilder sb, List<SQLParameter> list, AtomicBoolean mustTableAlias, DBDialect dialect) {
        if (value instanceof SimpleTable) {
            SimpleTable c = (SimpleTable) value;
            c.toSql(sb, list, dialect);
            return;
        }
        //以下是条件处理
        ColumnMapping[] columns = null;
        int columnSize = 0;
        if (fields != null) {
            columns = DSLMethod.columnList(sb, list, fields, mustTableAlias, true, dialect);
            columnSize = fields.length;
        }

        if (operator != null) {
            boolean operatorIsNothing = operator == DBOperator.NOTHING;
            if (!operatorIsNothing) {
                sb.append(' ').append(operator.getOper());
                if (value != null) {
                    sb.append(' ');
                }
            }
            if (value instanceof IField) {
                IField sf = (IField) value;
                sf.toConditionSql(sb, list, mustTableAlias, true, dialect);
            } else if (value instanceof Example) {
                String subQuery = "";
                Example subExample = (Example) value;
                subExample.dialect = dialect;
                SQLContext sqlContext = ExampleSQL.getSelectSQLContext(subExample, null, SelectOpt.all, true);
                subQuery = sqlContext.getSql();
                if (CollectionUtils.isNotEmpty(sqlContext.getParas())) {
                    list.addAll(sqlContext.getParas());
                }
                if (StringUtils.isNotBlank(subQuery)) {
                    sb.append('(').append(subQuery).append(')');
                }
            } else if (value instanceof ICondition) {
                ((ICondition) value).toSql(sb, list, mustTableAlias, dialect);
            } else if (value instanceof RawValue) {
                sb.append(((RawValue) value).getContext());
            } else {
                int plachholderSize = DSLMethod.addPlaceholder(sb, operator, columnSize, value, valueType, escape);
                DSLMethod.setSqlParameters(list, columnSize, columns, plachholderSize, value, valueType);
            }
        }
    }

    public SimpleField[] getFields() {
        return fields;
    }

    public void setFields(SimpleField[] fields) {
        this.fields = fields;
    }

    public DBOperator getOperator() {
        return operator;
    }

    public void setOperator(DBOperator operator) {
        this.operator = operator;
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    public ValueType getValueType() {
        return valueType;
    }

    public void setValueType(ValueType valueType) {
        this.valueType = valueType;
    }

    public String getEscape() {
        return escape;
    }

    public void setEscape(String escape) {
        this.escape = escape;
    }

}